package com.example.auv_660.util;

import java.util.HashMap;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

public enum ThreadPool {

    INSTANCE;

    private ThreadPoolProxy threadPoolProxy;

    ThreadPool() {
        threadPoolProxy = new ThreadPoolProxy();
    }

    public ThreadPoolProxy getThreadPoolProxy() {
        return threadPoolProxy;
    }

    public class ThreadPoolProxy {
        private static final int SCHEDULE_POOL_SIZE = 4;
        private static final int COMMON_POOL_SIZE = 5;
        private ScheduledExecutorService scheduledThreadPool;
        private ExecutorService commonThreadPool;
        private HashMap<Integer, Future<?>> scheduledThreadKey;

        private ThreadPoolProxy() {
            int processors = Runtime.getRuntime().availableProcessors();
            commonThreadPool = Executors.newFixedThreadPool(processors * COMMON_POOL_SIZE);
            scheduledThreadPool = Executors.newScheduledThreadPool(SCHEDULE_POOL_SIZE);
            scheduledThreadKey = new HashMap<>();
        }

        public int scheduledTask(TimerTask task, long milliseconds) {
            if (task != null && milliseconds >= 0) {
                ScheduledFuture<?> t = scheduledThreadPool.scheduleAtFixedRate(task, 0l, milliseconds, TimeUnit.MILLISECONDS);
                int threadKey = t.hashCode();
                scheduledThreadKey.put(threadKey, t);
                return threadKey;
            }
            return -1;
        }

        public void joinTask(Runnable task) {
            if (task != null) {
                commonThreadPool.execute(task);
            }
        }

        public void shutDownCommonPool() {
            if (!commonThreadPool.isShutdown()) {
                commonThreadPool.shutdown();
            }
        }

        public void shutDownScheduledTask(int threadKey) {
            if (scheduledThreadKey.containsKey(threadKey)) {
                scheduledThreadKey.get(threadKey).cancel(true);
            }
        }

    }

}
